import { _decorator, Component, Node, Sprite, SpriteFrame, UITransform, Color, Vec2 } from 'cc';
import { PerlinNoise } from './PerlinNoise';

const { ccclass, property } = _decorator;

@ccclass('MapGenerator')
export class MapGenerator extends Component {
    @property({ type: Number })
    mapWidth: number = 100;

    @property({ type: Number })
    mapHeight: number = 100;

    @property({ type: Number })
    scale: number = 20;

    @property({ type: Number })
    seed: number = Math.random();

    @property({ type: Number })
    octaves: number = 4;

    @property({ type: Number })
    persistence: number = 0.5;

    @property({ type: SpriteFrame })
    waterTexture: SpriteFrame | null = null;

    @property({ type: SpriteFrame })
    sandTexture: SpriteFrame | null = null;

    @property({ type: SpriteFrame })
    grassTexture: SpriteFrame | null = null;

    @property({ type: SpriteFrame })
    forestTexture: SpriteFrame | null = null;

    @property({ type: SpriteFrame })
    mountainTexture: SpriteFrame | null = null;

    @property({ type: SpriteFrame })
    snowTexture: SpriteFrame | null = null;

    private perlin: PerlinNoise = null!;
    private mapTiles: Node[][] = [];

    onLoad() {
        this.perlin = new PerlinNoise(this.seed);
        this.generateMap();
    }

    generateMap() {
        // 清除现有地图
        this.node.removeAllChildren();
        this.mapTiles = [];

        // 生成新地图
        for (let y = 0; y < this.mapHeight; y++) {
            this.mapTiles[y] = [];
            for (let x = 0; x < this.mapWidth; x++) {
                // 使用柏林噪声生成高度值
                const noiseValue = this.perlin.fractalNoise(
                    x / this.scale,
                    y / this.scale,
                    this.octaves,
                    this.persistence
                );

                // 根据噪声值确定地形类型
                const tileType = this.getTileType(noiseValue);

                // 创建地图瓦片
                const tileNode = new Node(`Tile_${x}_${y}`);
                const sprite = tileNode.addComponent(Sprite);
                const transform = tileNode.addComponent(UITransform);

                transform.setContentSize(32, 32);
                tileNode.setPosition(x * 32, y * 32);

                // 设置纹理
                switch (tileType) {
                    case 'water':
                        sprite.spriteFrame = this.waterTexture;
                        break;
                    case 'sand':
                        sprite.spriteFrame = this.sandTexture;
                        break;
                    case 'grass':
                        sprite.spriteFrame = this.grassTexture;
                        break;
                    case 'forest':
                        sprite.spriteFrame = this.forestTexture;
                        break;
                    case 'mountain':
                        sprite.spriteFrame = this.mountainTexture;
                        break;
                    case 'snow':
                        sprite.spriteFrame = this.snowTexture;
                        break;
                }

                this.node.addChild(tileNode);
                this.mapTiles[y][x] = tileNode;
            }
        }
    }

    private getTileType(noiseValue: number): string {
        // 将噪声值映射到不同的地形类型
        if (noiseValue < 0.3) return 'water';
        if (noiseValue < 0.35) return 'sand';
        if (noiseValue < 0.6) return 'grass';
        if (noiseValue < 0.7) return 'forest';
        if (noiseValue < 0.85) return 'mountain';
        return 'snow';
    }

    // 获取指定位置的地形类型
    getTileAt(x: number, y: number): string {
        if (x < 0 || x >= this.mapWidth || y < 0 || y >= this.mapHeight) {
            return 'water'; // 边界外默认为水
        }

        const noiseValue = this.perlin.fractalNoise(
            x / this.scale,
            y / this.scale,
            this.octaves,
            this.persistence
        );

        return this.getTileType(noiseValue);
    }

    // 重新生成地图（可用于游戏中的重新开始）
    regenerateMap(newSeed: number = Math.random()) {
        this.seed = newSeed;
        this.perlin = new PerlinNoise(this.seed);
        this.generateMap();
    }
}